#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
朋友列表面板

 - writer:linux_23; create: Fri Jun 06 13:56:47 2008 ; version:1; 创建
"""
import wx,sys,os
import wx.lib.foldpanelbar as fpb
import wx.lib.hyperlink as hl
import xmpp
from geosings.ui.core.wxKeyParser import *
import cStringIO
from gispanel import *

def GetUserDirPath():
    """获取图像文件夹路径
    @rtype: str
    @return: 图像文件夹的路径
    """
    bapath = os.path.expanduser('~')
    path = os.path.join(bapath,".9talk")
    if not os.access(path, os.R_OK):
        os.makedirs(path)
        os.makedirs(os.path.join(path,'avatar'))
    return path

class Avatar(xmpp.protocol.Protocol): 
    """ XMPP Iq object - get/set dialog mechanism. """
    def __init__(self, typ=None, queryNS=None, attrs={}, to=None, frm=None, aid=None, xmlns=xmpp.protocol.NS_CLIENT, node=None):
        """ Create Iq object. You can specify type, query namespace
            any additional attributes, recipient of the iq, sender of the iq, any additional payload (f.e. jabber:x:data node) and namespace in one go.
            Alternatively you can pass in the other XML object as the 'node' parameted to replicate it as an iq. """
        xmpp.protocol.Protocol.__init__(self, 'iq', to=to, typ=typ, attrs=attrs, frm=frm, xmlns=xmlns, node=node)
        self.setTag('vCard').setNamespace("vcard-temp")
    def getQueryNS(self):
        """ Return the namespace of the 'query' child element."""
        tag=self.getTag('vCard')
        if tag: return tag.getNamespace()

    def buildReply(self,typ):
        """ Builds and returns another Iq object of specified type.
            The to, from and query child node of new Iq are pre-set as reply to this Iq. """
        iq=Iq(typ,to=self.getFrom(),frm=self.getTo(),attrs={'id':self.getID()})
        if self.getTag('vCard'): iq.setQueryNS(self.getQueryNS())
        return iq

class FoldWindow(wx.Panel):
    class FoldItemPanel(wx.Panel):
        def __init__(self, parent, name):
            wx.Panel.__init__(self, parent, -1, style=wx.BORDER_SIMPLE)
            
            sizer = wx.BoxSizer(wx.VERTICAL)

            hep = wx.Panel(self, -1, style=wx.DOUBLE_BORDER)
            hep.SetBackgroundColour(wx.Colour(100,122,222))
            lab = wx.StaticText(hep, -1, name)
            hep.Bind(wx.EVT_LEFT_DOWN, self.LDown)
            sizer.Add(hep, 0, wx.EXPAND|wx.ALL, 0)

            self.SetSizer(sizer)
            self.SetAutoLayout(True)
            self.Layout()

        def LDown(self, evt):
            if self.dp1.IsShown():
                self.dp1.Hide()
            else:
                self.dp1.Show(True)
            self.ReLayout()

        def SetMainPanel(self, itemp):
            self.dp1 = itemp
            self.GetSizer().Add(itemp, 1, wx.EXPAND|wx.ALL, 0)
            self.ReLayout()

        def ReLayout(self):
            self.GetParent().Layout()
            self.GetParent().Refresh()

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        self.SetBackgroundColour(wx.WHITE)

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Layout()
    def AddFoldItem(self, name):
        dp1 = FoldWindow.FoldItemPanel(self, name)
        self.GetSizer().Add(dp1, 0, wx.EXPAND|wx.ALL, 5)
        self.Layout()
        return dp1

class LoginPanel(wx.Panel):
    def __init__(self, parent, successFoo):
        wx.Panel.__init__(self, parent, -1)
        self.successFoo = successFoo
        #self.SetBackgroundColour(wx.WHITE)
        vsizer = wx.BoxSizer(wx.VERTICAL)
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer = wx.BoxSizer(wx.VERTICAL)

        sizer.Add(wx.StaticText(self, -1, u"您的用户名"), 1, wx.ALL, 0)
        name = wx.TextCtrl( self,-1, "")
        sizer.Add(name, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
        sizer.Add(wx.StaticText(self, -1, u"您的登陆密码"), 1, wx.ALL, 0)
        pwd = wx.TextCtrl( self,-1, "")
        sizer.Add(pwd, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
        #sizer.Add((30,30))
        loginbut = wx.Button( self, -1, u'登陆')
        self.Bind(wx.EVT_BUTTON, self.OnClick, loginbut)
        sizer.Add(loginbut, 0, wx.ALIGN_CENTER|wx.ALL, 10)

        hsizer.Add((30,30), 1, wx.EXPAND, 0)
        hsizer.Add(sizer, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, 0)
        hsizer.Add((30,30), 1, wx.EXPAND, 0)
        vsizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
        vsizer.Add(hsizer, 1, wx.EXPAND, wx.ALL , 30)
        self.SetSizer(vsizer)
        self.SetAutoLayout(True)
        self.Layout()
        self.GetSizer().Fit(parent)
        self.GetSizer().SetSizeHints(self)
        self.GetSizer().Layout()
        
    def OnClick(self, evt):
        self.successFoo(MainBookPanel)

class TalkDialog(wx.Frame):
    def __init__(self, parent, name, cnx):
        wx.Frame.__init__(self, parent, -1)
        self.cnx = cnx
        self.name = name
        self.SetSize((300,300))
        self.SetTitle(u"正在和："+name+u" 的对话")
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.history = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_RICH2|wx.NO_3D)
        sizer.Add(self.history, 1, wx.EXPAND|wx.ALL, 0)
        self.totalk = wx.TextCtrl(self, -1, "", 
                style=wx.TE_MULTILINE|wx.TE_RICH2|wx.TE_PROCESS_ENTER,
                size=(100,50))
        self.totalk.Bind(wx.EVT_CHAR, self.OnChar)
        sizer.Add(self.totalk, 0, wx.EXPAND|wx.ALL, 10)
        self.SetSizer(sizer)
        sizerh = wx.BoxSizer(wx.HORIZONTAL)
        sizerh.Add((10,10), 1, wx.EXPAND, 0)
        sizer.Add(sizerh, 0, wx.EXPAND|wx.ALL, 10)
        self.SetAutoLayout(True)
        self.Layout()

    def OnSend(self, evt):
        print self.cnx.send( xmpp.Message( self.name ,self.totalk.GetValue() ) )
        self.history.AppendText(u"我："+self.totalk.GetValue()+'\n')
        self.totalk.SetValue("")
    def SendMsg(self, msg):
        body = unicode(msg.getBody())
        msgfrom = unicode(msg.getFrom().node)
        self.history.AppendText(msgfrom+":"+body+'\n')
    def OnChar(self, evt):
        kp = KeyParser(evt)
        keycode = kp.keycode
        if keycode==13:# enter
            print self.cnx.send( xmpp.Message( self.name ,self.totalk.GetValue() ) )
            self.history.AppendText(u"我："+self.totalk.GetValue()+'\n')
            self.totalk.SetValue("")
        else:evt.Skip(True)

class FriendItemPanel(wx.Panel):
    def __init__(self, parent, name, id, cnx):
        wx.Panel.__init__(self, parent, -1)
        self.selection = False
        self.name = name
        self.showinfo = ""
        self.avatar = None
        self.namecol = wx.Colour(215,215,215)
        self.cnx = cnx
        self.win = None
        #self.SetBackgroundColour(wx.BLUE)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add((30,50))
        #self.nametext = wx.StaticText(self, -1, name)
        #sizer.Add(self.nametext, 0, wx.ALL, 3)
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Layout()
        self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnClick)
        self.Bind(wx.EVT_LEFT_DCLICK, self.OnDClick)
        self.Bind(wx.EVT_PAINT, self.__OnPaint)
    def SendMsg(self, msg):
        if self.win:
            self.win.SendMsg(msg)
    def SetStatus(self, statusstr):
        status,self.showinfo = statusstr.split(':')
        print status,'*'*100
        if status=='dnd':
            self.namecol = wx.RED
        elif status:
            self.namecol = wx.GREEN
            #获取用户头像
            iq=Avatar('get',xmpp.protocol.NS_PUBSUB,to=self.name)
            self.cnx.send( iq )
        else:
            self.namecol = wx.Colour(215,215,215)
        self.Refresh()
    def SetAvatar(self, bin):
        filename = os.path.join(GetUserDirPath(),'avatar',self.name+".png")
        file = open(filename,'wb')
        file.write(bin)
        file.close()
        img = wx.Image(filename, wx.BITMAP_TYPE_ANY)
        self.avatar = img
        self.Refresh()
    def __OnPaint(self, evt):
        dc = wx.PaintDC(self)
        dc.Clear()
        self.PrepareDC(dc)
        dc.BeginDrawing()
        dc.SetBrush(wx.Brush(self.namecol))
        if self.avatar:
            dc.DrawBitmap(self.avatar.Scale(40,40).ConvertToBitmap(), 5, 5, True)
        dc.DrawEllipse(50,5,10,10)
        dc.DrawText(self.name, 70, 0)
        dc.DrawText(self.showinfo, 50, 20)
        dc.EndDrawing()
    def OnEnter(self, evt):
        if not self.selection:
            self.SetBackgroundColour(wx.Colour(215,215,225))
            self.Refresh()
    def OnLeave(self, evt):
        if not self.selection:
            self.SetBackgroundColour(wx.WHITE)
            self.Refresh()
    def OnClick(self, evt):
        self.selection = not self.selection
        self.SetBackgroundColour(wx.Colour(100,100,155))
        self.Refresh()
    def OnDClick(self, evt):
        if not self.win:
            self.win = TalkDialog(self,self.name,self.cnx)
        self.win.Show(True)
        self.win.SetFocus()

class LoginDialog(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, -1)
        #self.SetBackgroundColour(wx.WHITE)
        vsizer = wx.BoxSizer(wx.VERTICAL)
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer = wx.BoxSizer(wx.VERTICAL)

        sizer.Add(wx.StaticText(self, -1, u"您的用户名"), 1, wx.ALL, 0)
        self.name = name = wx.TextCtrl( self,-1, "", size=(150,-1))
        sizer.Add(name, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
        sizer.Add(wx.StaticText(self, -1, u"您的登陆密码"), 1, wx.ALL, 0)
        self.pwd = pwd = wx.TextCtrl( self,-1, "")
        sizer.Add(pwd, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
        sizer.Add((30,30))
        loginbut = wx.Button( self, wx.ID_OK, u'登陆')
        #self.Bind(wx.EVT_BUTTON, self.OnClick, loginbut)
        sizer.Add(loginbut, 0, wx.ALIGN_CENTER|wx.ALL, 10)

        hsizer.Add((30,30), 1, wx.EXPAND, 0)
        hsizer.Add(sizer, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, 0)
        hsizer.Add((30,30), 1, wx.EXPAND, 0)
        vsizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
        vsizer.Add(hsizer, 1, wx.EXPAND, wx.ALL , 30)
        self.SetSizer(vsizer)
        self.SetAutoLayout(True)
        self.Layout()
        self.GetSizer().Fit(parent)
        self.GetSizer().SetSizeHints(self)
        self.GetSizer().Layout()
    def GetName(self):
        return self.name.GetValue()
    def GetPwd(self):
        return self.pwd.GetValue()
        
class GTalkPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        #self.SetSize((100,300))
        self.parent = parent
        self.cnx = None
        
        sizer = wx.BoxSizer(wx.VERTICAL)

        self._hyper = hl.HyperLinkCtrl(self, wx.ID_ANY,
                                        u"登陆",
                                        URL="")
        self._hyper.Bind(hl.EVT_HYPERLINK_LEFT, self.Login)
        self._hyper.SetToolTip(wx.ToolTip(u"登陆google talk"))
        self._hyper.AutoBrowse(False)
        sizer.Add(self._hyper, 0, wx.EXPAND, 0)

        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Layout()

    def Login(self,evt):
        dlg = LoginDialog(self)
        if dlg.ShowModal()==wx.ID_OK:
            self._hyper.SetLabel(u"正在登陆")
            login = dlg.GetName()#login = 'linux23maillist' # @gmail.com
            pwd   = dlg.GetPwd()
            #friend = 'lilin.maillist@gmail.com'
            self.cnx = xmpp.Client('gmail.com')
            self.cnx.connect( server=('talk.google.com',5223) )
            self.cnx.auth(login,pwd, u'')
            self.cnx.sendInitPresence()
            self._hyper.SetLabel(u"退出")
            r = self.cnx.getRoster()
            users = r.keys()

            #users = ['asdf','bbbb','cccc']
            self.umap = {}
            i = 1
            for user in users:
                f =FriendItemPanel(self, user, i, self.cnx)
                self.umap[user]=f
                self.GetSizer().Add(f, 1, wx.EXPAND, 0)
                i+=1

            self.cnx.RegisterHandler('presence',self.presenceHandler)
            self.cnx.RegisterHandler('iq',self.iqHandler)
            self.cnx.RegisterHandler('message', self.messageCB)
            

            #self.GetSizer().Fit(self.parent)
            #self.GetSizer().SetSizeHints(self)
            self.GetSizer().Layout()
            self.Layout()
            self.parent.ReLayout()

            self.timer = wx.Timer(self)#创建定时器
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)#绑定一个定时器事件
            self.timer.Start(3000)#设定时间间隔
        
    def OnTimer(self, evt):
        if self.cnx:
            self.cnx.Process(1)

    def presenceHandler(self, conn,presence_node):
        """ Handler for playing a sound when particular contact became online """
        r = self.cnx.getRoster()
        jid = presence_node.getFrom()
        who = jid.node+'@'+jid.domain
        t = presence_node.getType()
        if t == 'unavailable':
            self.umap[unicode(who)].SetStatus(':')
        elif r.getShow(unicode(jid))=='dnd' and not r.getStatus(unicode(jid)):
            self.umap[unicode(who)].SetStatus('dnd: ')
        elif r.getStatus(unicode(jid))=="" or r.getStatus(unicode(jid))==None:
            self.umap[unicode(who)].SetStatus('online: ')
        else:
            self.umap[unicode(who)].SetStatus( \
                    unicode(r.getShow(unicode(jid)))+":" \
                    +unicode(r.getStatus(unicode(jid))))
        #self.umap[unicode(who)].SetShow(r.getShow(unicode(jid)))
        #None是不在，有内容是在线的状态
        #print r.getName(presence_node.getFrom())

    def iqHandler(self, conn,iq_node):
        """ Handler for processing some "get" query from custom namespace"""
        #reply=iq_node.buildReply('result')
        # ... put some content into reply node
        #conn.send(reply)
        #raise NodeProcessed  # This stanza is fully processed
        r = self.cnx.getRoster()
        jid = iq_node.getFrom()
        who = jid.node+'@'+jid.domain

        import base64
        bin = iq_node.T.vCard.T.PHOTO.T.BINVAL.getData()
        #print bin.getData()
        binval = base64.b64decode(bin)
        self.umap[unicode(who)].SetAvatar(binval)
        #file = open('f:/9talk/a.png','wb')
        #file.write(binval)
        #file.close()
        pass

    def messageCB(self, conn, msg):
        print '******************************'
        print "from: " + unicode(msg.getFrom())
        print dir(msg.getFrom())
        print msg.getFrom().domain
        print msg.getFrom().node
        who = msg.getFrom().node+'@'+msg.getFrom().domain
        body = unicode(msg.getBody())
        print "Content: " + body
        print '******************************'
        self.umap[unicode(who)].SendMsg(msg)

class FriendPanel(wx.ScrolledWindow):
    def __init__(self, parent):
        wx.ScrolledWindow.__init__(self, parent, -1)
        #self.SetBackgroundColour(wx.Colour(180,200,255))
        #self.SetSize((300,400))
        self.EnableScrolling(False, True)
        
        self.ReCreateFoldPanel(fpb.FPB_SINGLE_FOLD)
        self.Bind(wx.EVT_SIZE, self.OnSize)
    def OnSize(self, evt):
        #print evt.GetSize()
        self.SetVirtualSize((evt.GetSize()[0]-30,400))
        self.SetScrollRate(20,20)
        self.Layout()

    def ReCreateFoldPanel(self, fpb_flags):
        # recreate the foldpanelbar
        sizer = wx.BoxSizer(wx.VERTICAL)
        #self._pnl = fpb.FoldPanelBar(self, -1, wx.DefaultPosition,
        #                             wx.DefaultSize, fpb.FPB_DEFAULT_STYLE, fpb_flags)


        #item = self._pnl.AddFoldPanel("google talk", collapsed=False)
        #self._pnl.AddFoldPanelWindow(item, GTalkPanel(item)) 

        #item = self._pnl.AddFoldPanel("MSN", collapsed=True)
        #button2 = wx.Button(item, wx.NewId(), "Collapse All")        
        #self._pnl.AddFoldPanelWindow(item, button2) 

        #item = self._pnl.AddFoldPanel("GIS", collapsed=True)
        #self._pnl.AddFoldPanelWindow(item, LoginPanel(item, None),
        #                             fpb.FPB_ALIGN_WIDTH, 5, 20) 
        
        #style = fpb.CaptionBarStyle()
        #style.SetCaptionStyle(fpb.CAPTIONBAR_FILLED_RECTANGLE)
        #CAPTIONBAR_GRADIENT_V CAPTIONBAR_GRADIENT_H CAPTIONBAR_SINGLE CAPTIONBAR_RECTANGLE CAPTIONBAR_FILLED_RECTANGLE
        #self._pnl.ApplyCaptionStyleAll(style)
        #self.SizeWindows()
        mp = FoldWindow(self)
        sizer.Add(mp,1,wx.EXPAND,0)

        item1 = mp.AddFoldItem('google talk')
        dp1 = GTalkPanel(item1)
        item1.SetMainPanel(dp1)
        item2 = mp.AddFoldItem('MSN')
        button2 = wx.Button(item2, wx.NewId(), "Collapse All")        
        item2.SetMainPanel(button2)
        #item3 = mp.AddFoldItem('GIS')
        #dp3 = GISDriverPanel(item3)
        #item3.SetMainPanel(dp3)

        #sizer.Add(self._pnl, 1, wx.EXPAND, 0)
        
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Layout()
        
